﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zeta.Common;
using Zeta.Navigation;
using Zeta;
using Zeta.Internals.Actors;
using Zeta.TreeSharp;

namespace IncubusCC.Helpers
{
    public static class Avoidance
    {
        public static IEnumerable<Vector3> GeneratePossibleTargetPoints(this Vector3 center, float radius, int numberOfPoints = 16)
        {
            double fullCircle = 2 * Math.PI;
            var center2 = new Vector2(center.X, center.Y);

            for (int i = 0; i < numberOfPoints; i++)
            {
                Vector3 point3D = new Vector3(0, 0, 0);
                try
                {
                    double alpha = (fullCircle / numberOfPoints) * i;
                    float x = center2.X + (float)Math.Cos(alpha) * radius;
                    float y = center2.Y + (float)Math.Sin(alpha) * radius;
                    Vector2 point = new Vector2(x, y);
                    float z = Navigator.SearchGridProvider.GetHeight(point);
                    Vector3 tempPoint = new Vector3(x, y, z);
                    if (ZetaDia.Physics.Raycast(center, tempPoint, Zeta.Internals.SNO.NavCellFlags.AllowWalk))
                        point3D = tempPoint;
                }
                catch (Exception ex)
                {
                    Logger.WriteVerbose("Error generating point: {0}", ex.Message);
                }
                if (point3D.X != 0 || point3D.Y != 0 || point3D.Z != 0)
                    yield return point3D;
            }
        }

        private static List<string> m_PossibleAoeStartStrings = new List<string>()
        {
            "spore",
            "monsteraffix_arcaneenchanted",
            "monsteraffix_frozen_iceclusters",
            "monsteraffix_plagued",
            "monsteraffix_molten_trail",
            "monsteraffix_molten_deathstart",
            "monsteraffix_desecrator",
        };

        public static bool IsAoeWithinRange(this Vector3 position, float range)
        {
            return ZetaDia.Actors.GetActorsOfType<DiaObject>().Where(o => position.Distance2D(o.Position) <= range && o.IsAoe()).Any();
        }

        public static bool IsAoe(this DiaObject obj)
        {
            if (obj.IsValid)
            {
                return m_PossibleAoeStartStrings.Any(s => obj.Name.ToLower().StartsWith(s));
            }
            return false;
        }

        public static Composite CreateAvoidance(float checkRadius, float movementRadius)
        {
            return
                new Decorator(
                    ctx => ZetaDia.Me.Position.IsAoeWithinRange(checkRadius),
                    new Zeta.TreeSharp.Action(
                        ctx =>
                        {
                            var possiblePoints = ZetaDia.Me.Position.GeneratePossibleTargetPoints(movementRadius).Where(v => !v.IsAoeWithinRange(checkRadius));
                            if (possiblePoints.Any())
                                Navigator.MoveTo(possiblePoints.First());
                        }
                    )
                );
        }
    }
}
